package com.scalar.chiptrack.adaptor.wipfed;

import com.scalar.chiptrack.adaptor.AdaptorConstants;
import com.scalar.chiptrack.adaptor.AdaptorUtils;
import com.scalar.chiptrack.adaptor.FabSortLot;
import com.scalar.chiptrack.adaptor.dao.FabSortAdaptorDAO;
import com.scalar.chiptrack.adaptor.dao.AdaptorRunInfo;
import com.scalar.chiptrack.adaptor.dao.NewAdaptorDAO;
import com.scalar.chiptrack.jobs.JobHandler;
import com.scalar.chiptrack.utils.Logger;
import com.scalar.chiptrack.utils.ConfigManager;
import com.scalar.chiptrack.utils.Mailer;
import com.scalar.chiptrack.utils.StringUtils;
import com.scalar.chiptrack.operations.dataentry.LotDetails;
import com.scalar.chiptrack.users.notification.dao.NotificationDAO;
import com.scalar.chiptrack.commons.Constants;
import com.scalar.ScalarException;

import java.util.HashMap;
import java.util.ArrayList;
import java.util.Iterator;

import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * User: ChandraSekhar
 * Date: Jun 20, 2007
 * Time: 12:54:07 PM
 */
public class WipFedSortParser extends JobHandler implements AdaptorConstants
{
    private static Logger m_parserLogger    = null;
    private String m_dataOutputDir          = null;
    private ArrayList m_binDataList         = new ArrayList();
    private ArrayList m_NoPartNoList        = new ArrayList();
    private HashMap discrepancyMap          = new HashMap();

    public WipFedSortParser() throws ScalarException
    {
        try
        {
            m_dataOutputDir = ConfigManager.getWipFedSortSheetDirectory();
            AdaptorUtils.makeAllAdaptorDirs( m_dataOutputDir );
            m_parserLogger = AdaptorUtils.getDataParserLogger( m_dataOutputDir,"WIPFED SORT");
            AdaptorUtils.setLogger( m_parserLogger);
            FabSortAdaptorDAO.setLogger( m_parserLogger );   // All the DAOs and Parser should be logging into same file
        }
        catch ( Exception se )
        {
            log( "ERROR!! ERROR!! ERROR!! Exception while loading WipFed Sort output directory details from database, Exception: " + se );
         }
    }
    /**
     *
     * @param args
     * @throws Exception
     */
    public static void main( String args[] ) throws Exception
    {
        new WipFedSortParser().execute();
    }

    /**
     *
     */
    public void execute() throws Exception
    {
        AdaptorUtils.printHeader("WIPFED SORT", CONSTANT_PARSER );

        File doneDestDir = new File( m_dataOutputDir + "/done" );

        File wipFedSortDataoutDir = new File( m_dataOutputDir );

        File[] fileList = wipFedSortDataoutDir.listFiles();

        if ( ( fileList == null ) || ( fileList.length <= 3 ) )
        {
            log( "No file found in directory: " + wipFedSortDataoutDir );
            throw new ScalarException( "No file found in directory: " + wipFedSortDataoutDir + "----\n\n" );
        }

        ArrayList successFileList   = new ArrayList();
        boolean success             = false;

        try
        {
            for ( int i = 0; i < fileList.length; i++ )
            {
                if ( fileList[i].isDirectory() == true )
                {
                    continue;
                }

                if ( ( fileList[i].getName() != null ) && ( fileList[i].getName().trim().startsWith( WipFedSortAdaptor.FILE_NAME_WAFER_INVTY ) ) )
                {
                    try
                    {
                        ArrayList m_sortBinDataList = parseSortWaferInvyReport( fileList[i].getAbsolutePath() );

                        if ( m_sortBinDataList != null && m_sortBinDataList.size() > 0 )
                        {
                            discrepancyMap = updateSortBinDataDetails( m_sortBinDataList );
                        }
                        successFileList.add( fileList[i] );
                        success = true;
                    }
                    catch ( Exception e )
                    {
                        success = false;
                        log( "Exception while parsing and storing file: " + fileList[i].getAbsolutePath() + "\nException: " + e );
                        e.printStackTrace();
                        throw e;
                    }
                }
            }
        }
        catch ( Exception e )
        {
            success = false;
            log( "ERROR!! ERROR!! ERROR!! While parsing and storing File " + e );
            e.printStackTrace();
            throw e;
        }
        // to save the Fab lot tables
        try
        {
            log( "Saving sort Bin Information");
            if ( m_binDataList != null && m_binDataList.size() > 0 )
            {
                FabSortAdaptorDAO.saveWipFedSortBinData( null, m_binDataList.iterator() );
            }
            m_binDataList = null;
            success = true;
        }
        catch ( Exception e )
        {
            success = false;
            log( "ERROR!! ERROR!! ERROR!! Could not update WipFed Sort Bin information into database: " + e );
            e.printStackTrace();
            throw e;
        }

        if ( discrepancyMap != null && discrepancyMap.size() > 0 )
        {
             m_NoPartNoList.addAll( discrepancyMap.values() );
            notifyUserAboutInvalidPartNumbers ( m_NoPartNoList );
            m_NoPartNoList = null;
            discrepancyMap = null;
        }

        int adaptor_id = AdaptorRunInfo.getLastRunAdaptorId( WipFedSortAdaptor.ADAPTOR_NAME, CONSTANT_ADAPTOR);

        // Update Adaptor_Run_Info table
        try
        {
            if ( success == true )
            {
                AdaptorRunInfo.saveAdaptorLastUpdatedStatus(CONSTANT_PARSER, WipFedSortAdaptor.ADAPTOR_NAME, CONSTANT_SUCCESS, adaptor_id);
                System.out.println( "SUCCESSFULLY UPDATED IN THE DATABASE" );
            }
        }
        catch ( ScalarException se )
        {
            success = false; //As filES DATA SAVED , UPDATEING AS SUCCESS
            AdaptorRunInfo.saveAdaptorLastUpdatedStatus(CONSTANT_PARSER, WipFedSortAdaptor.ADAPTOR_NAME, CONSTANT_SUCCESS, adaptor_id);
            log( "WARNING!! WARNING!! WARNING!! Could not update Adaptor run information, Exception: " + se );
            throw se;
        }
        // Move the successful files to 'done' directory
       if ( success )
       {
           AdaptorUtils.moveFilesToDone( successFileList, doneDestDir );
       }
    }//end of execute method
        

    /** PARSES THE DETAILS BUMP/CP SHIP SHEET DATA INTO ARRAY LIST
     *
     * @param fileName
     * @return
     * @throws Exception
     */
    private ArrayList parseSortWaferInvyReport( String fileName ) throws Exception
    {
        if ( fileName == null ) throw new ScalarException( "Filename argument is null" );

        ArrayList sortBinList   = new ArrayList();
        String line             = null;

        try
        {
            File detailBinDataFile = new File( fileName );
            if ( detailBinDataFile.exists() == false )
            {
                throw new ScalarException( fileName + " doesnt exist" );
            }

            log( "\nFound " + fileName );
            log( "\nParsing the file for Sort Wafer Inv Report..." );
            System.out.println( "\nFound " + fileName );
            System.out.println( "\nParsing the file for Sort Wafer Inv Report..." );

            BufferedReader reader = new BufferedReader( new FileReader( detailBinDataFile ) );
            reader.readLine();  // Read out <Ship Date> Line

            while ( ( line = reader.readLine() ) != null  && line.length() > 0 )
            {
                WipFedStatus wipfedStatus = new WipFedStatus();

                line = line.replaceAll( "\"", "" );
                String[] token = line.split( "," );

                for (int x = 0; x < token.length; x++)
                {
                    if (token[x] != null && token[x].trim().length() > 0)
                    {
                        switch (x)
                        {
                            case 0:
                                    wipfedStatus.setDivision(token[x].trim() );
                                    break;
                            case 1:
									wipfedStatus.setDiePart(token[x].trim() );
                                    break;
                            case 2:
                                    wipfedStatus.setProdLoc( token[x].trim() );  //Die_Loc
                                    break;
                            case 3:
                                    wipfedStatus.setLotNumber( token[x].trim() ); //  fabLot
                                    break;
                            case 4:
                                    wipfedStatus.setSplit( token[x].trim() );     //fabSplit
                                    break;
                            case 5:
                                    wipfedStatus.setDevice( token[x].trim());
                                    break;
                            case 6:
                                    wipfedStatus.setWaferID( token[x].trim() );    //wafer
                                    break;
                            case 7:
                                    wipfedStatus.setDieQty( token[x].trim() );  //Qty
                                    break;
                            case 8:
                                    wipfedStatus.setGrade( token[x].trim());
                                    break;
                            case 9:
                                    wipfedStatus.setStep ( token[x].trim());
                                    break;
                            case 10:
                                    wipfedStatus.setStatus( token[x].trim() );
                                    break;
                            case 11:
                                    wipfedStatus.setThickness ( token[x].trim());
                                    break;
                            case 12:
                                    wipfedStatus.setAge( token[x].trim() );
                                    break;
                            /*case 13:
                                    wipfedStatus.setMrb( token[x].trim());
                                    break;
                            case 14:
                                    wipfedStatus.setBin( token[x].trim());
                                    break;*/
                            case 13:
                                    wipfedStatus.setLocation( token[x].trim());
                                    break;
                           }
                    }
                }
                sortBinList.add( wipfedStatus );
            }

            try
            {
                if ( reader != null )
                {
                   reader.close();
                }
            }
            catch(IOException ignore)
            {

            }
        }
        catch ( Exception ex )
        {   System.out.println("ERROR!!!ERROR!!! While Parsing the WipFed Sort Bin Sheet");
            ex.printStackTrace();
            throw ex;
        }
        return sortBinList;
    } // end of prase WipFed Sort Bin wafer Inv. Report method


    /**
    * @param allsortBinDataList
    * @throws Exception
    */
    private HashMap updateSortBinDataDetails( ArrayList allsortBinDataList ) throws Exception
    {
        if ( allsortBinDataList == null || allsortBinDataList.size() == 0 )
        {
            return new HashMap();
        }

        FabSortLot   sortBinLot = null;
        WipFedStatus  wipStatus = null;
        String partNumber       = null;
        String lotNumber        = null;
        String vendorName       = null;
        int waferId          = 0;
        HashMap  dataNotFoundInSheetMap = null;

        try
        {
            HashMap partNoandLotNoMap = NewAdaptorDAO.getAllRunningandHoldLots( LOCATION_TYPE_DIE_BANK, LOCATION_TYPE_DIE_BANK );

            dataNotFoundInSheetMap = (HashMap) partNoandLotNoMap.clone();

            Iterator iterator = allsortBinDataList.iterator();

            while ( iterator.hasNext() )
            {
                wipStatus = ( WipFedStatus ) iterator.next();

                try
                {
                    waferId = Integer.parseInt( wipStatus.getWaferID() );
                }
                catch(NumberFormatException nfe)
                {
                    waferId = 0;
                }

                if ( wipStatus.getDevice() != null && wipStatus.getLotNo() != null  && waferId > 0 )
                {
                    //For Removing the LAST CHARaCTER IN THE DEVICE NAME
                    partNumber   = wipStatus.getDevice().substring( 0, wipStatus.getDevice().length()-1 );

                    lotNumber = wipStatus.getLotNo();

                    if( wipStatus.getProdLoc() != null && "R".equalsIgnoreCase( wipStatus.getProdLoc() ) )
                    {
                        vendorName = VENDOR_NAME_CML;
                    }
                    else if( wipStatus.getProdLoc() != null && "T".equalsIgnoreCase( wipStatus.getProdLoc()))
                    {
                        vendorName = VENDOR_NAME_OSET;
                    }
                    else if( wipStatus.getProdLoc() != null && "MM".equalsIgnoreCase( wipStatus.getProdLoc() ) )
                    {
                        vendorName = VENDOR_NAME_CMI;
                    }
                    else if ( wipStatus.getProdLoc() != null && "L".equalsIgnoreCase(wipStatus.getProdLoc()))
                    {
                        vendorName = VENDOR_NAME_ATK;
                    }

                    sortBinLot = new FabSortLot();

                    sortBinLot.setWaferID( waferId+"" );
                    sortBinLot.setQtyIn( wipStatus.getDieQty() );

                    if ( partNoandLotNoMap.containsKey( partNumber + lotNumber + vendorName ) )
                    {
                        dataNotFoundInSheetMap.remove( partNumber + lotNumber + vendorName );

                        LotDetails lotDetails = (LotDetails) partNoandLotNoMap.get( partNumber + lotNumber + vendorName );
                        sortBinLot.setLotId( lotDetails.getLotId() );

                        m_binDataList.add( sortBinLot );
                    }
                }
            }
        }
        catch( Exception e )
        {

        }

        return dataNotFoundInSheetMap;
    }

     /**
     * To send the Alert mail to user, When the Part Number are invalid
     * @param invalidPartNoList
     * @throws Exception
     */
    private void notifyUserAboutInvalidPartNumbers( ArrayList invalidPartNoList ) throws Exception
    {

        LotDetails lotDetails   = null;
        String[] emailArray     = null;

        String from = ConfigManager.getScalarAdminEmail();
        int index = from.lastIndexOf( "\\" );
        from = from.substring( index + 1, from.length() );
        emailArray = NotificationDAO.loadEmailsByNSType( null, LOCATION_TYPE_DIE_BANK , Constants.DISCREPENCY_LOT_NOTIFICATION );
        String to = StringUtils.concatStrings ( emailArray, Mailer.EMAIL_SEPARATOR );
        String subject = "Sort Bin Info Not Found for DIE BANK Lots";

        // FORMAT MESSAGE
        StringBuffer buf = new StringBuffer( 2098 );
        buf.append( "<HTML><HEAD></HEAD><BODY>" );
        buf.append( "<TABLE ALIGN = 'CENTER' style='FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Verdana' borderColor='#ffffff' cellSpacing='1' cellPadding='3' width='50%' border=0>" );
        buf.append( "<TR bgColor='#ccccff'><TD colspan='5' width='100%' align='center' ><B> Sort Bin Info Not Found for DIE BANK Lots  <B></TD>" );
        buf.append( "<TR bgColor='#e6e6e6'><TD width='2%' align='CENTER'><B>SL NO.<B></TD><TD width='8%' align='CENTER'><B>CUSTOMER PRODUCT<B></TD><TD width='8%' align='CENTER'><B>LOT NUMBER<B></TD>" );
        buf.append( "<TD width='8%' align='CENTER'><B>VENDOR NAME<B></TD><TD width='8%' align='CENTER'><B>QTY IN<B></TD></TR>" );
        int srNo = 1;
        for (int i = 0; i < invalidPartNoList.size(); i++)
        {
            lotDetails = ( LotDetails ) invalidPartNoList.get( i );
           
            if ( !lotDetails.getVendorName().equalsIgnoreCase(VENDOR_NAME_OSEP ) && !lotDetails.getVendorName().equalsIgnoreCase(VENDOR_NAME_SPEL )                     )
            {
                buf.append( "<TR bgColor='#e6e6e6'><TD width='2%' align='CENTER'>" ).append( ( srNo ) + "." );
                buf.append( "</TD><TD width='8%' align='CENTER'>" + lotDetails.getPartNumber() + "</TD>" );
                buf.append( "<TD width='8%' align='CENTER'>" + lotDetails.getLotNumber() + "</TD>" );
                buf.append( "<TD width='8%' align='CENTER'>" + lotDetails.getVendorName() + "</TD>" );
                buf.append( "<TD width='8%' align='CENTER'>" + lotDetails.getDieQtyIn() + "</TD></TR>" );

                srNo ++;
            }
        }
        
        buf.append( "</TR></TABLE><BODY></HTML>\n" );
        String message = buf.toString();
        try
        {
            // SEND MESSAGE
            Mailer.send( from, to, null, null, subject, message, null, Mailer.CONTENT_TYPE_HTML, false );
        }
        catch ( ScalarException e )
        {
            throw new ScalarException( "Exception while sending InValid PartnUmber mail notification" );
        }
    }
    /**
     *
     * @param message
     */
    private static void log( String message )
    {

        if ( message == null ) return;

        if ( m_parserLogger != null )
        {
            synchronized ( m_parserLogger )
            {
                m_parserLogger.logDebug( message + LINE_SEPARATOR );
            }
        }
        else
        {
            System.out.println( message );
        }
    }
    /**
     *
     */
    private void printVersionInfo()
    {
           String info = "\n\n+----------- Running WipFed Sort Data Parser on " + new java.util.Date( System.currentTimeMillis() ) + " -------------+\n" +
                    "\n+---------------------------------------------------------------+\n" +
                    "+                                                                \n" +
                    "+            WipFed Sort Data Interpreter - Beta          \n" +
                    "+                                                                \n" +
                    "+    Copy Right (C) 2007 - ScalarSoft Inc., All rights reserved.  \n" +
                    "+                                                                \n" +
                    "+---------------------------------------------------------------+\n" ;
           System.out.println( info );
           log( info );
    } //end of printVersionInfo
}
